package com.chuanke.ckfamily.service.social.impl;

import com.chuanke.ckfamily.dao.base.CkUtil;
import com.chuanke.ckfamily.dao.common.model.IncomeConf;
import com.chuanke.ckfamily.dao.social.FamilyFinanceDao;
import com.chuanke.ckfamily.dao.social.model.Family;
import com.chuanke.ckfamily.dao.social.model.FamilyFinance;
import com.chuanke.ckfamily.service.base.FailCode;
import com.chuanke.ckfamily.service.common.CacheService;
import com.chuanke.ckfamily.service.common.IncomeConfService;
import com.chuanke.ckfamily.service.common.SynizedExcuter;
import com.chuanke.ckfamily.service.common.impl.RedisLockUtil;
import com.chuanke.ckfamily.service.constant.FamilyFinanceInOrOut;
import com.chuanke.ckfamily.service.constant.IncomeChannel;
import com.chuanke.ckfamily.service.constant.PacketFinaceType;
import com.chuanke.ckfamily.service.exception.CFException;
import com.chuanke.ckfamily.service.finance.FamilyDayIncomeService;
import com.chuanke.ckfamily.service.finance.UserDayIncomeService;
import com.chuanke.ckfamily.service.social.FamilyFinanceService;
import com.chuanke.ckfamily.service.social.FamilyService;
import com.chuanke.ckfamily.service.social.impl.vo.FamilyIncome;
import com.weijie.core.BaseBiz;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Date;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

@Service
@Transactional(rollbackFor = Exception.class)
public class FamliyFinanceServiceImpl extends BaseBiz<FamilyFinance, FamilyFinanceDao> implements FamilyFinanceService {

	private static final Logger log = LoggerFactory.getLogger(FamliyFinanceServiceImpl.class);

	@Autowired
	private FamilyService familyService;

	@Autowired
	private IncomeConfService incomeConfService;

	@Autowired
	private FamilyDayIncomeService familyDayIncomeService;

	@Autowired
	private UserDayIncomeService userDayIncomeService;

	@Autowired
	private CacheService cacheService;

	@Override
	@Scheduled(cron = "0/1 * * * * ?")
	public void excuteIncomeTask() {
		new SynizedExcuter() {
			@Override
			public void excute() {
				FamliyFinanceServiceImpl.this.excuteFamilyIncomeTask();
			}
		}.run(cacheService, CacheService.KEY_PREFIX.family_income_task.name(), 2000);

	}

	private void excuteFamilyIncomeTask() {
		log.debug("excuteIncomeTask=========> begin");
		FamilyIncome familyIncome = (FamilyIncome) cacheService.rightPop(CacheService.KEY_PREFIX.family_income_queue.name());
		if (familyIncome == null) {
			log.debug("用户家族不存在");
			return;
		}

		Date time = new Date(System.currentTimeMillis());
		String date = new SimpleDateFormat("yyyy-MM-dd").format(time);

		RedisLockUtil redisLock = null;
		try {
			log.debug("excute income task======>uid={}, channel={}", familyIncome.getUid(), familyIncome.getChannel());
			userDayIncomeService.addUserIncome(familyIncome.getChannel(), familyIncome.getUid(), familyIncome.getIc().getPrice(), date);
			redisLock = cacheService.getLock(CacheService.KEY_PREFIX.family_finace.name() + familyIncome.getUid());
			if (enableFamilyChannel(familyIncome.getFamily(), familyIncome.getUid(), familyIncome.getChannel(), familyIncome.getIc().getNumber(), date)) {
				FamilyFinance ff = new FamilyFinance();
				ff.setUid(familyIncome.getUid());
				ff.setFid(familyIncome.getFamily().getId());
				ff.setIn_or_out(FamilyFinanceInOrOut.INT.getInOrOut()); // 增加为1
				ff.setFmoney(familyIncome.getIc().getPrice());
				ff.setOptype(PacketFinaceType.FAMILY_INCOME.getType());
				ff.setOpchannel(familyIncome.getChannel());
				ff.setCreatetime(new Timestamp(System.currentTimeMillis()));
				ff.setF_date(new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())));
				save(ff);

				log.debug("===============================>f={}", ff);
				familyDayIncomeService.addNewIncome(familyIncome.getUid(), ff.getFmoney());
			}

		} catch (Exception e) {
			e.printStackTrace();

		} finally {
			if (redisLock != null) {
				redisLock.unlock();
			}

		}
	}

	@Override
	public boolean addIncome(Long uid, Long channel) throws CFException {
		if (uid == null || channel == null) {
			throw new CFException(FailCode.APP, "参数为空");
		}

		// 根据操作类型找到对应的奖励
		IncomeConf ic = incomeConfService.findById(channel);
		if (ic == null) {
			throw new CFException(FailCode.APP, "操作类型参数有误");
		}

		// 查找家族成员
		log.debug("add income =====> uid={}, channel={}", uid, channel);
		Family family = familyService.findFamilyByUserId(uid);
		cacheService.leftPush(CacheService.KEY_PREFIX.family_income_queue.name(), new FamilyIncome(uid, channel, ic, family));
		return true;
	}

	@Override
	public FamilyFinance findByChannel(Long uid, Long channel, java.util.Date time) {
		// 如果channel是2 渠道 拉粉丝 则不用查询数据库
		if (channel == null || channel == IncomeChannel.INVITE_CHANNEL.getType()) {
			return null;
		}

		Map<String, Object> param = new HashMap<>();
		param.put("date", new SimpleDateFormat("yyyy-MM-dd").format(time));
		param.put("uid", uid);
		param.put("channel", channel);

		return this.baseDao.findFamilyFinanceByChannel(param);
	}

	private boolean enableFamilyChannel(Family family, Long uid, Long channelId, Integer icNum, String date) {
		if (family == null) {
			return false;
		}

		if (icNum < 0) {
			return true;
		}

		Map<String, Object> param = new HashMap<>(4);
		param.put("fid", family.getId());
		param.put("uid", uid);
		param.put("channel", channelId);
		param.put("date", date);
		Integer count = baseDao.findFinanceCountByChannel(param);
		return count < icNum;
	}

	@Override
	public void familyCount(Long fid, Long allMoney, Long leaderMoney, Long superLeaderMoney, Long redpacketMoney) {
		Family family = familyService.findById(fid);
		if (family == null) {
			return;
		}

		RedisLockUtil redisLock = null;
		try {
			redisLock = cacheService.getLock(CacheService.KEY_PREFIX.family_income.name() + fid);
			family = familyService.findById(fid);

			Family f = new Family();
			f.setId(family.getId());
			f.setFamily_income_sum(CkUtil.sumMoney(family.getFamily_income_sum(), allMoney));
			f.setOwner_income_sum(CkUtil.sumMoney(family.getOwner_income_sum(), leaderMoney));
			f.setSuper_income_sum(CkUtil.sumMoney(family.getSuper_income_sum(), superLeaderMoney));
			// f.setPacket_income_sum(CkUtil.sumMoney(family.getPacket_income_sum(), redpacketMoney));
			log.debug("====================>allmoney={}, owenmoney={}, supermoney={}, redpacketMoney={}", allMoney, leaderMoney, superLeaderMoney, redpacketMoney);
			familyService.update(f);

		} catch (Exception e) {
			e.printStackTrace();

		} finally {
			if (redisLock != null) {
				redisLock.unlock();
			}

		}
	}
}